const WebSocket = require("ws");
// 新增mysql模块引入
const operations = require("./db/db-operations");
const cors = require("cors");
const sql = require("./db/sql");
const login = require("./db/login");
const register = require("./db/register");
const profile = require("./db/profile");
const { keysToCamelCase } = require("./db/utils");
const otsdb = new operations({});

const express = require("express");
const app = express();

// 中间件配置
app.use(cors()); // 允许跨域
app.use(express.json()); // JSON解析

// 测试数据库是否链接成功
otsdb.testConnection();

// 定期健康检查
setInterval(async () => {
  const isHealthy = await otsdb.checkHealth();
  if (!isHealthy) {
    console.warn('数据库连接不健康，尝试重新连接...');
    await otsdb.testConnection();
  }
}, 30000); // 每30秒检查一次
// 创建WebSocket服务器，监听8080端口
const wss = new WebSocket.Server({ port: 9088, host: '0.0.0.0' });
// 用于存储所有连接的客户端及其标识符
const clients = new Map();
wss.on("connection", (ws, req) => {
  if (!req.url.startsWith("/ws/chat")) {
    console.error("非法路径:", req.url);
    ws.close();
    return;
  }
  // 为每个客户端分配一个唯一的标识符
  const urlParams = new URL(req.url, `http://${req.headers.host}`).searchParams;
  const userId = urlParams.get("userId");
  console.log("用户连接:", userId);
  const clientId = userId;
  clients.set(String(clientId), ws);
  // 检查是否保存成功
  if (clients.get(clientId) !== ws) {
    console.error(`会话保存失败: ${clientId}`);
  } else {
    console.log(`会话保存成功: ${clientId}`);
  }

  // 监听客户端发送的消息
  ws.on("message", async (messageData) => {
    const { receiver, message, send, nickName, onNickName } = JSON.parse(messageData);
    console.log(`收到消息: ${message}`);
    console.log(`发送人: ${send}`);
    console.log(`接收人: ${receiver}`);

    // 确保 receiver 是字符串
    const receiverStr = String(receiver);

    // 打印调试信息
    console.log("当前 clients 键:", Array.from(clients.keys()));
    console.log("尝试获取的 receiver:", receiverStr);

    let sendReceiver = "测试用户";
    // 存储消息到数据库
    let params = {
      receiver,
      message,
      sendReceiver,
      send,
      nickName,
      onNickName,
      // 修改：确保 sender 不为 undefined
    };
    console.log("存储的参数:", params);
    try {
      let res = await sql.insertMessage(params);
      console.log("消息存储成功:", res);
    } catch (error) {
      console.error("消息存储失败:", error);
      // 发送错误消息给发送者
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
          type: 'error',
          message: '消息发送失败，请稍后重试',
          error: error.message
        }));
      }
      return; // 如果存储失败，不继续处理消息转发
    }
    // 根据目标标识符查找客户端并发送消息
    const targetClient = clients.get(receiverStr);
    if (!targetClient) {
      console.error(`目标客户端不存在: ${receiverStr}`);
    } else if (targetClient.readyState !== WebSocket.OPEN) {
      console.error(`目标客户端状态异常: ${receiverStr}, 当前状态: ${targetClient.readyState}`);
    }

    if (targetClient && targetClient.readyState === WebSocket.OPEN) {
      targetClient.send(
        JSON.stringify({ send: send, receiver: receiver, message,nickName,onNickName })
      );
    } else {
      console.log("目标客户端不存在或未打开");
    }
  });

  // 监听客户端断开连接
  ws.on("close", () => {
    console.log("客户端断开连接", clientId);
    clients.delete(clientId);
  });
});

console.log("WebSocket服务器已启动，监听端口8080");

app.use(express.json());

// 登录接口
app.post("/login", (req, res) => {
  // 实现登录逻辑
  login.login(req, res);
});

// 用户注册接口
app.post("/register", (req, res) => {
  // 实现注册逻辑
  register.register(req, res);
});

// 获取个人信息接口
app.get("/profile", (req, res) => {
  profile.getProfile(req, res);
});

// 修改个人信息接口
app.put("/profile", (req, res) => {
  profile.updateProfile(req, res);
});

// 用户验证中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization?.split(" ")[1];
  if (!token) {
    return res.status(401).json({ success: false, message: "未授权" });
  }

  jwt.verify(token, JWT_SECRET, (err, decoded) => {
    if (err) {
      return res.status(401).json({ success: false, message: "无效令牌" });
    }
    req.user = decoded; // 将解码的用户信息添加到请求对象
    next();
  });
};
// 用户列表接口
app.get("/users", async (req, res) => {
  try {
    const currentUserId = req.query.userId; // 从查询参数获取当前用户ID
    if (!currentUserId) {
      return res.status(400).json({
        success: false,
        message: "缺少用户ID参数",
      });
    }
    const users = await sql.getAllUsers(currentUserId);
    
    // 将用户数据转换为小驼峰格式
    const camelCaseUsers = keysToCamelCase(users);
    
    res.status(200).json({
      success: true,
      message: "获取用户列表成功",
      code: 200,
      data: camelCaseUsers
    });
  } catch (error) {
    console.error("获取用户列表错误:", error);
    res.status(500).json({
      success: false,
      message: "服务器错误，请稍后再试",
    });
  }
});
// 聊天记录 (分页)
app.get("/messages", async (req, res) => {
  try {
    const userId = req.query.userId; // 从查询参数获取当前用户ID
    const onUserId = req.query.onUserId; // 从查询参数获取对方用户ID
    const page = parseInt(req.query.page) || 1; // 页码，默认为1
    const limit = parseInt(req.query.limit) || 100; // 每页数量，默认为100
    
    
    if (!userId || !onUserId) {
      return res.status(400).json({
        success: false,
        message: "缺少用户ID参数",
      });
    }
    
    // 获取消息列表
    const messages = await sql.getAllMessages({ userId, onUserId, page, limit });
    
    // 获取总消息数
    const total = await sql.getMessageCount({ userId, onUserId });
    
    // 判断是否还有更多历史消息
    const hasMore = page * limit < total;
    
    // 反转消息数组，使旧消息在前，新消息在后
    const reversedMessages = messages.reverse();
    
    res.status(200).json({
      success: true,
      message: "获取聊天记录成功",
      code: 200,
      data: {
        messages: reversedMessages.map((msg) => ({
          message: msg.message,
          send: msg.send_user_id,
          receiver: msg.on_user_id,
          createTime: msg.create_time,
          nickName: msg.send_nick_name,
          onNickName: msg.on_nick_name
        })),
        total: total,
        hasMore: hasMore,
        page: page,
        limit: limit
      }
    });
  } catch (error) {
    console.error("获取聊天记录错误:", error);
    res.status(500).json({
      success: false,
      message: "服务器错误，请稍后再试",
    });
  }
});

// 启动HTTP服务器
app.listen(8090, () => {
  console.log("HTTP服务器已启动，监听端口8090");
});
